﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GridMove : MonoBehaviour
{
    enum PAUSE_STATE
    {
        NONE,
        GAMEOVER,
        PAUSE,
        HIT
    }
    private PAUSE_STATE game_state = PAUSE_STATE.NONE;
    private bool IS_ATTACKING = false;
    private float SPEED = 1;     //移动速度

    // 移动方向，向量
    private Vector3 m_direction;
    private Vector3 m_move_vector;
    private Vector3 m_current_grid;

    private float HITCHECK = 0f;

    private GameControl game_ctrl;
    void Start()
    {
        m_move_vector = Vector3.zero;
        m_direction = Vector3.zero;
        m_current_grid = transform.position;
        game_ctrl = GameObject.FindWithTag("GameCtrl").GetComponent<GameControl>();
    }

    void Update()
    {
        if(!IS_ATTACKING)
            AttackJudge();
        if (game_state != PAUSE_STATE.NONE || game_ctrl.IsPause())
        {
            m_move_vector = Vector3.zero;
        }
        else
        {
            if (Time.deltaTime <= 0.1f)
                Move(Time.deltaTime);
            else
            {
                int n = (int)(Time.deltaTime / 0.1f) + 1;
                for (int i = 0; i < n; i++)
                    Move(Time.deltaTime / (float)n);
            }
        }
    }

    public void Move(float t)
    {
        Vector3 pos = transform.position;

        pos += m_direction * SPEED * t;

        bool across = false;
        if ((int)pos.x != (int)transform.position.x)
            across = true;
        if ((int)pos.z != (int)transform.position.z)
            across = true;

        Vector3 near_grid = new Vector3(Mathf.Round(pos.x), pos.y, Mathf.Round(pos.z));
        m_current_grid = near_grid;
        Vector3 forward_pos = pos + m_direction * 0.5f;
        if (Mathf.RoundToInt(forward_pos.x) != Mathf.RoundToInt(pos.x) ||
            Mathf.RoundToInt(forward_pos.z) != Mathf.RoundToInt(pos.z))
        {
            Vector3 tpos = m_current_grid;
            tpos.y -= HITCHECK;
            if (Physics.Raycast(tpos, m_direction, 1.0f))
            {
                pos = near_grid;
                across = true;
            }
        }
        if (across || (pos - near_grid).magnitude < 0.00005f ||
            Mathf.Abs(transform.position.x) < 0.005f ||
            Mathf.Abs(transform.position.z) < 0.005f)
            SendMessage("OnGrid", pos);

        if (game_state == PAUSE_STATE.HIT)
        {
            SendMessage("OnGrid", pos);
            game_state = PAUSE_STATE.NONE;
        }

        m_move_vector = (pos - transform.position) / t;
        transform.position = pos;
    }
    public void ChangeSpeed(float spd)
    {
        SPEED = spd;
    }

    public bool WallCheck(Vector3 direction)
    {
        Vector3 tpos = m_current_grid;
        tpos.y -= HITCHECK;
        bool check = Physics.Raycast(tpos, direction, 1.0f);
        if (check)
            game_state = PAUSE_STATE.HIT;
        return check;
    }
    public bool IsReverseDirection(Vector3 dis)
    {
        if (Vector3.Dot(dis, m_direction) <= -0.99f)
            return false;
        else
            return true;
    }
    public void SetDirection(Vector3 direction)
    {
        m_direction = direction;
    }
    public Vector3 GetDirection()
    {
        return m_direction;
    }
    public bool Is_Running()
    {
        if (m_move_vector.magnitude >= 0.05f)
            return true;
        else
            return false;
    }
    public Vector3 GetForwardDis(int PorN, int ghost_type)
    {
        Vector3 target = Vector3.zero;
        Ray ray1 = new Ray(transform.position, m_direction);
        Ray ray2 = new Ray(transform.position, -m_direction);
        RaycastHit hitInfo1;
        RaycastHit hitInfo2;
        if (Physics.Raycast(ray1, out hitInfo1) && Physics.Raycast(ray2, out hitInfo2))
        {
            if (PorN == 1)
                target = hitInfo1.transform.position - m_direction;
            else if (PorN == -1)
                target = hitInfo2.transform.position + m_direction;
            if (hitInfo1.transform.tag.Equals("Player"))
            {
                target = hitInfo1.transform.position;
            }

            if (hitInfo2.transform.tag.Equals("Player"))
            {
                target = hitInfo2.transform.position;
            }
        }
        else
        {
            target = Vector3.zero;
        }


        return target;
    }
    void AttackJudge()
    {
        Collider[] cs = Physics.OverlapSphere(transform.position, 1f);
        if (cs.Length != 0)
        {
            foreach (Collider csCell in cs)
            {
                if (csCell.transform.tag.Equals("ghost")&&this.transform.tag.Equals("Player"))
                {
                    if (GetComponent<Weapon>())
                    {
                        Weapon a = GetComponent<Weapon>();
                        if (a.CanAutoAttack())
                        {
                            a.m_attackaTar = csCell.transform;
                            StartCoroutine(a.SwordAutoAttack());
                            IS_ATTACKING = true;
                        }
                    }
                }
                else if (csCell.transform.tag.Equals("Player") && this.transform.tag.Equals("ghost"))
                {
                    GetComponent<MonsterCtrl>().Attack(csCell.transform);
                    IS_ATTACKING = true;
                }
            }
        }
    }

    public bool IsAttacking
    {
        get => IS_ATTACKING;
        set => IS_ATTACKING = value;
    }
}
